package com.zs.propertymanage.aop;

import com.zs.propertymanage.annotation.SystemLog;
import com.zs.propertymanage.dataObj.entity.Log;
import com.zs.propertymanage.mapper.LogMapper;
import com.zs.propertymanage.utils.JwtUtil;
import com.zs.propertymanage.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.UUID;

@Component  // 注册为Bean
@Aspect     // 切面类
public class LogAspect {

    @Autowired
    private LogMapper logMapper;

    @Pointcut("@annotation(com.zs.propertymanage.annotation.SystemLog)")
    public void logPointCut() {
        // 此处为切点表达式，寻找谁加了上面的那个“Log”注解
        // 加了“Log”注解的方法就会被增强，进入到下面对应的环绕通知中
    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

        Log log = new Log();
        // id (UUID)
        log.setId(UUID.randomUUID().toString());
        // 操作时间
        log.setRequestDate(LocalDateTime.now());

        // 获取被增强类和方法的信息
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;

        // 获取被增强的方法对象
        Method method = methodSignature.getMethod();
        // 从方法中解析出注解
        if (method != null) {
            // 模块名
            log.setModuleName(method.getAnnotation(SystemLog.class).name());
            // 方法名字
            log.setMethodName(method.getName());
        }

        // 通过工具类获取Request对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            // 获取HttpServletRequest对象
            HttpServletRequest request = requestAttributes.getRequest();
            // 访问url
            log.setRequestUrl(request.getRequestURI());
            // 请求方式
            log.setRequestMethod(request.getMethod());
            // 请求ip
            log.setRequestIp(request.getRemoteAddr());
        }

        // 执行被切面的方法
        Object result = joinPoint.proceed();

        // token (从ThreadLocalUtil中获取token要在方法执行后)
        try {
            Map<String, Object> claims = JwtUtil.parseToken(ThreadLocalUtil.get());
            log.setUserId((String) claims.get("id"));
            log.setUserName((String) claims.get("name"));
            log.setUserIdentity((String) claims.get("identity"));
        } catch (Exception ignored) {
        }

        logMapper.insertLog(log);

        return result;
    }

}
